#include "includes.h"

struct host_cmd {
	char *host_name;
	char *cmd;
	struct list_head list;
};
char* local_hostname;
	
char *send_msg(char *msg, char *host, int portno) {

    struct hostent *server;
	struct sockaddr_in serv_addr;
	int sockfd, n;
	char *in_msg;

	//DEBUGPRINT("msg %s to %s\n", msg, host);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
	//DEBUGPRINT("Opened socket %d\n", sockfd);
    if (sockfd < 0) {
        DEBUGPRINT("ERROR opening socket :\n", NULL);
        return NULL;
	}
	
	//DEBUGPRINT("Getting host by name\n", NULL);

    server = gethostbyname(host);


	//DEBUGPRINT("Getting host by name : DONE\n", NULL);

    if (server == NULL) {
        DEBUGPRINT("ERROR, no such host :\n", NULL);
		return NULL;
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
	
	//DEBUGPRINT("About to connect\n", NULL);

    n = connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
    if(n < 0) {
		DEBUGPRINT("ERROR connecting\n", NULL);
		return NULL;
	}

	//DEBUGPRINT("Connected\n", NULL);

	char *tmp_m;
	int len;
	len = strlen(msg);	
	tmp_m = (char *) malloc(6);
	bzero((char *) tmp_m, 6);
	sprintf(tmp_m, "%d", len);

	char l[6];
	my_itoa(strlen(msg), l);
	l[5] = '\0';

	write(sockfd, l, 6);
    n = write(sockfd,msg,strlen(msg));
    if (n < 0) {
         DEBUGPRINT("ERROR writing to socket\n", NULL);
         return NULL;
	}

	//DEBUGPRINT("message sent\n", NULL);

	n = strlen(msg);	
	

	in_msg = (char *) malloc(4096);
	bzero((char *)in_msg, 4096);
	
    n = read(sockfd,in_msg,4095);

	if (n < 0) {
        DEBUGPRINT("ERROR reading from socket\n", NULL);
         return NULL;
	}
	close(sockfd);

	//DEBUGPRINT("RESPONSE %s\n", in_msg);
	if(strlen(in_msg) == 0) {
		return NULL;
	} else {
		return in_msg;
	}
}


//client -port 8080 -commandfile pathToCommandFile id
int main(int argc, char *argv[]) {
	int port, id, len;
	char *in_file;
	char entry[512];
	FILE *fp;
	char *host, *cmd;
	char *host_id_val;
	char *resp;
	int host_id;
	struct msg_client_update *cu;
	int counter = 0;
	
	port = atoi(argv[2]);
	in_file = argv[4];
	id = atoi(argv[5]);
    fp = fopen (in_file, "r");

	
	local_hostname = (char *) malloc(512);
	bzero((char *) local_hostname, 512);
	gethostname(local_hostname, 512);
    
    //DEBUGPRINT("TEST\n", NULL);

	/*
	xinu01.cs.purdue.edu;One
	xinu01.cs.purdue.edu;Two
	xinu03.cs.purdue.edu;Three
	xinu04.cs.purdue.edu;Four
	*/
	while(fgets(entry, 512, fp) != NULL) {
		len = strlen(entry);
		if(entry[len-1] == '\n') {
			entry[len-1] = 0;
		}
		
		//DEBUGPRINT("ENTRY: %s\n", entry);
		
		host = strtok(entry, ";");
		cmd = strtok(NULL, ";");
		
		//Get host id
		host_id_val = send_msg("HOST_ID:X", host, port);
		if(host_id_val != NULL) {
			char *tmp;
			//DEBUGPRINT("HOST ID VAL : %s", host_id_val);
			host_id = atoi(host_id_val);
		
			//DEBUGPRINT("HOST ID : %d\n", host_id);
		
			cu = create_client_update(id, host_id, counter, cmd);
			DEBUGPRINT("SENDING PROPOSAL %s TO %s\n",cmd,host);
			resp = send_msg(serialize_client_update(cu), host, port);
		
			if(resp == NULL) {
				//server crashed
				DEBUGPRINT("UNABLE TO SEND %s to %s\n", cmd, host);
			} else {
				DEBUGPRINT("PROPOSAL %s SENT TO %s RESULTED IN DECISION OK\n", cmd,host);
			}
			counter++;
		}
	}
	
}

int get_hostnum(char* host){

	char chnum[3];
	chnum[0] = host[4];
	chnum[1] = host[5];
	chnum[2] = '\0';
	return atoi(chnum);
}

/* Convert an Integer to a Character String */
int my_itoa(int val, char* buf){

	const unsigned int radix = 10;

	char* p;
	unsigned int a;
	int len;
	char* b;
	char temp;
	unsigned int u;

	p = buf;

	if (val < 0)
	{
		*p++ = '-';
		val = 0 - val;
	}

	u = (unsigned int)val;
	b = p;

	do{
		a = u % radix;
		u /= radix;

		*p++ = a + '0';

	} while (u > 0);

	len = (int)(p - buf);
	*p-- = 0;

	do{
		temp = *p;
		*p = *b;
		*b = temp;
		--p;
		++b;

	} while (b < p);

	return len;
}
